package com.gioneco.util;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
 * @author djl
 */
@Component
@Aspect
public class EnableStateTransition {

    @AfterReturning(returning = "object", value = "@annotation(com.gioneco.util.StateTransition)")
    public void enableStationTransition(JoinPoint joinPoint, Object object) {
        if (ObjectUtils.isEmpty(object)) {
            return;
        }
        //集合处理
        if (object instanceof Collection) {
            //切入点
            Signature signature = joinPoint.getSignature();
            collectionDispose((Collection) object, signature);
            return;
        }

        try {
            //单对象及对象包含集合处理
            Class<?> clazz = object.getClass();
            objectDispose(clazz, object, joinPoint);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private void objectDispose(Class<?> clazz, Object object, JoinPoint joinPoint) throws Exception {
        for (Field field : clazz.getDeclaredFields()) {
            field.setAccessible(true);
            Object o = null;
            o = field.get(object);
            if (o instanceof Collection) {
                //切入点
                Signature signature = joinPoint.getSignature();
                collectionDispose((Collection) o, signature);
            }
        }
        fieldsTransition(object, null);
    }

    /**
     * 集合处理
     */
    private void collectionDispose(Collection object, Signature signature) {
        object.forEach(obj -> {
            try {
                fieldsTransition(obj, signature);
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
    }

    private void fieldsTransition(Object object, Signature signature) throws Exception {
        if (ObjectUtils.isEmpty(object)) {
            return;
        }
        Class<?> clazz = object.getClass();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            //枚举转换
            enumTransition(field, object);
        }
    }

    /**
     * 枚举转换
     */
    private void enumTransition(Field field, Object object) throws Exception {
        Class<?> clazz = object.getClass();
        //单笔业务件状态处理
        FieldTag fieldTag = field.getAnnotation(FieldTag.class);
        if (!ObjectUtils.isEmpty(fieldTag)) {
            //获取枚举类
            Class<?> value = fieldTag.enumType();
            if (value.isEnum()) {
                Object[] enumConstants = value.getEnumConstants();
                List<Method> list = new ArrayList<>();
                for (Field var1 : value.getDeclaredFields()) {
                    if (var1.isAnnotationPresent(com.gioneco.util.Field.class)) {
                        String var1Name = var1.getName();
                        String var2Name = "get" + var1Name.substring(0, 1).toUpperCase() + var1Name.substring(1);
                        Method method = value.getMethod(var2Name);
                        list.add(method);
                    }
                }
                //获取属性的值
                String str = field.get(object) + "";
                String fieldName = field.getName();
                //获取Code对应的Name
                Field field1 = clazz.getDeclaredField(fieldName);
                field1.setAccessible(true);
                if (!StringUtils.isEmpty(str)) {
                    for (Object obj : enumConstants) {
                        // 3.调用对应方法，得到枚举常量中字段的值
                        String invoke = (String) list.get(0).invoke(obj);
                        String invoke1 = (String) list.get(1).invoke(obj);
                        if (str.equals(invoke)) {
                            field1.set(object, invoke1);
                        }
                        if (str.equals(invoke1)) {
                            field1.set(object, invoke);
                        }
                    }
                }
            }
        }
    }


    public StateTransition getAnnotation(Signature signature) throws ClassNotFoundException {
        //切入的类名
        String declaringTypeName = signature.getDeclaringTypeName();
        Class<?> objClazz = Class.forName(declaringTypeName);
        //获取切入方法
        Method metd = null;
        //获取该类所有方法
        Method[] declaredMethods = objClazz.getDeclaredMethods();
        for (Method method : declaredMethods) {
            if (method.getName().equals(signature.getName())) {
                metd = method;
            }
        }
        //获取方法上的注解
        StateTransition annotation = null;
        if (!ObjectUtils.isEmpty(metd)) {
            metd.setAccessible(true);
            annotation = metd.getAnnotation(StateTransition.class);
        }
        return annotation;
    }

}
